home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Games
/
xmris
/
monster.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
13KB
|
585 lines
/*{{{ (C) 1992 Nathan Sidwell*/
/*****************************************************************************
X M R I S V1.01
---------------
(C) 1992 Nathan Sidwell
This program is copyright (C) 1992 Nathan Sidwell. This software and documentation
is in the public domain. Permission is granted to distribute and compile
verbatim copies of this software for non-commercial, non-profit use,
without fee. The software may be modified, provided that both the above copyright
notice and this permission notice appear.
No guarantee is given as to the robustness or suitability of this
software for your computer.
Nathan Sidwell INMOS UK | | nathan@inmos.co.uk DoD#0390
*****************************************************************************/
/*}}}*/
#include "xmris.h"
/*{{{ prototypes*/
static void extra_dies PROTOARGLIST((void));
/*}}}*/
/*{{{ MONSTER *extra_escape()*/
extern MONSTER *extra_escape FUNCARGVOID
/*
* remove the extra monster from the top, so it
* can run around
*/
{
int x;
extra.escape = 1;
x = XTRA_X + extra.select * XTRA_SPACING;
XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
x, XTRA_Y, CELL_WIDTH, CELL_HEIGHT);
add_background(x, XTRA_Y, CELL_WIDTH, CELL_HEIGHT);
x -= BORDER_LEFT + GAP_WIDTH;
assert(x % (CELL_WIDTH + GAP_WIDTH) % VEL_X == 0);
return spawn_monster(2, 1, 1, x / (CELL_WIDTH + GAP_WIDTH), 0,
x % (CELL_WIDTH + GAP_WIDTH), XTRA_Y - BORDER_TOP);
}
/*}}}*/
/*{{{ void extra_dies()*/
static void extra_dies FUNCARGVOID
/*
* the extra monster has died,
* put it back at the top
* and maybe alter the state
*/
{
unsigned got;
if(global.state == 2)
{
global.state = 3;
monster.den = 0;
monster.delay = 0;
}
got = extra.got & (1 << extra.select);
extra.got |= 1 << extra.select;
extra.escape = 0;
if(!got)
create_xtra_monster(extra.select);
draw_extra();
return;
}
/*}}}*/
/*{{{ void fall_monsters()*/
extern void fall_monsters FUNCARGVOID
/*
* makes all the monsters fall
*/
{
unsigned i;
MONSTER *mptr;
for(mptr = monster.list, i = monster.monsters; i--; mptr++)
if(mptr->apple)
{
/*{{{ just hit?*/
if(mptr->face < 8)
{
if(BOARDCELL(mptr->cell.x, mptr->cell.y)->distance ==
monster.nearest)
global.difficulty++;
new_face(mptr);
if(mptr == &monster.list[0])
mptr->shot = 1;
else
{
mptr->chew = 0;
if(mptr->type < 2)
monster.normals--;
else if(mptr->type == 2)
extra_dies();
else if(mptr->type == 3)
monster.drones--;
}
}
/*}}}*/
mptr->pixel.y = mptr->apple->pixel.y + CELL_HEIGHT;
if(mptr->apple && mptr->apple->state > 3)
{
if(mptr->type != 4)
mptr->type = 5;
else
mptr->apple = NULL;
}
}
return;
}
/*}}}*/
/*{{{ void move_monsters()*/
extern void move_monsters FUNCARGVOID
/*
* moves all the monsters
*/
{
MONSTER *mptr;
unsigned i;
unsigned nearest;
unsigned farthest;
nearest = 255;
farthest = 0;
for(mptr = &monster.list[1], i = monster.monsters - 1; i--; mptr++)
{
if(mptr->shot || (mptr->type == 3 && global.state == 3))
/*{{{ shot*/
{
if(BOARDCELL(mptr->cell.x, mptr->cell.y)->distance ==
monster.nearest)
global.difficulty++;
if(mptr->type < 2)
monster.normals--;
else
/*{{{ convert to apple*/
{
APPLE *aptr;
CELL *cptr;
if(mptr->type == 2)
extra_dies();
else if(mptr->type == 3)
monster.drones--;
if(mptr->offset.x > (CELL_WIDTH + GAP_WIDTH) / 2)
{
mptr->offset.x -= CELL_WIDTH + GAP_WIDTH;
mptr->cell.x++;
}
else if(mptr->offset.x < -(CELL_WIDTH + GAP_WIDTH) / 2)
{
mptr->offset.x += CELL_WIDTH + GAP_WIDTH;
mptr->cell.x--;
}
cptr = BOARDCELL(mptr->cell.x, mptr->cell.y);
aptr = spawn_apple(mptr->cell.x, mptr->cell.y,
mptr->offset.x, mptr->offset.y);
if(mptr->cell.y == CELLS_DOWN - 1)
aptr->state = 2;
else if(mptr->offset.y < cptr->depths[1])
aptr->state = 2;
else if(!mptr->offset.y && cptr[CELL_STRIDE].visit)
{
aptr->state = 1;
aptr->count = APPLE_ROCK_DELAY;
}
}
/*}}}*/
if(mptr->shot)
add_score(500, mptr->pixel.x + CELL_WIDTH / 2,
mptr->pixel.y + CELL_HEIGHT / 2);
mptr->type = 5;
}
/*}}}*/
else if(mptr->apple)
/*EMPTY*/;
else if(mptr->chew)
/*{{{ chewing*/
{
if(mptr->chew == 1)
{
mptr->chew = 2;
mptr->count = CHOMP_DELAY;
mptr->image = 0;
mptr->cycle = MONSTER_CYCLES - 1;
}
mptr->count--;
if(!mptr->count)
mptr->chew = 0;
if(!mptr->cycle)
{
mptr->image = (mptr->image + 1) % MONSTER_IMAGES;
mptr->cycle = MONSTER_CYCLES;
}
mptr->cycle--;
}
/*}}}*/
else if(global.state != 4)
{
CELL *cptr;
cptr = BOARDCELL(mptr->cell.x, mptr->cell.y);
assert((cptr->distance || global.broken) && cptr->visit);
if(!mptr->cycle)
{
mptr->cycle = MONSTER_CYCLES;
mptr->image++;
if(mptr->image == MONSTER_IMAGES)
mptr->image = 0;
}
if((!mptr->count || mptr->type & 2) && !mptr->pause)
mptr->cycle--;
if(mptr->type & 2 || global.state != 2)
{
if(nearest > cptr->distance)
nearest = cptr->distance;
if(farthest < cptr->distance)
farthest = cptr->distance;
}
switch(mptr->type)
{
/*{{{ case 0: case 1: (normal or muncher)*/
case 0: case 1:
{
int valid;
valid = valid_directions(mptr, cptr);
if(mptr->count)
mptr->count--;
if(!mptr->type && random() < CONT_TOGGLE_PROB)
/*{{{ toggle the cont & maybe turn round*/
{
mptr->cont = !mptr->cont;
if(mptr->pause || mptr->stop)
{
mptr->dir ^= 1;
new_face(mptr);
}
}
/*}}}*/
if(mptr->push)
/*{{{ disable left or right*/
{
if(mptr->push < 0)
valid &= 0x77;
else
valid &= 0xBB;
}
/*}}}*/
else if(mptr->count)
valid = 0;
else if(mptr->pause)
{
if(!mptr->type)
{
if(random() < GO_MUNCH_PROB * global.difficulty)
mptr->gomunch = 1;
valid = 0;
}
else if(mptr->stop || random() < PUSH_TURN_PROB)
{
mptr->dir ^= 1;
new_face(mptr);
valid = 0;
}
mptr->stop = 0;
mptr->pause = 0;
}
else if(global.state == 2)
valid = 0;
else if(!mptr->offset.x && !mptr->offset.y)
{
mptr->fast = 0;
if(!mptr->type && global.state == 3)
mptr->fast = 1;
if(mptr->gomunch)
{
mptr->gomunch = 0;
mptr->type = 1;
mptr->count = GO_MUNCH_DELAY;
}
else if(mptr->type)
{
int temp;
temp = valid & 0xF;
if((temp & -temp) != temp)
{
APPLE *aptr;
unsigned i;
int x;
mptr->type = 0;
mptr->count = STOP_MUNCH_DELAY;
valid = 0;
x = mptr->pixel.x - CELL_WIDTH + GAP_WIDTH * 2;
for(aptr = apple.list, i = apple.apples; i--; aptr++)
{
if(!aptr->state && aptr->pixel.x - x >= 0 &&
aptr->pixel.x - x < CELL_WIDTH * 2 - GAP_WIDTH * 4 &&
aptr->cell.y == mptr->cell.y - 1)
{
aptr->state = 1;
aptr->count = APPLE_ROCK_DELAY;
}
}
}
}
else if(!mptr->type && random() <
GO_MUNCH_PROB * global.difficulty)
mptr->gomunch = 1;
}
if(!valid)
/*EMPTY*/;
else if(mptr->type)
/*{{{ move the muncher*/
{
if(mptr->offset.x || mptr->offset.y)
/*{{{ carry on*/
{
CELL *nptr;
nptr = move_muncher(mptr);
if(nptr)
{
cptr = nptr;
if(nptr->sprite == SPRITE_CHERRY)
{
global.cherries--;
nptr->sprite = 0;
}
}
}
/*}}}*/
else
/*{{{ pick new direction*/
{
int temp;
temp = ~valid & 0xF;
if(!mptr->cell.y)
temp &= 0xE;
else if(mptr->cell.y == CELLS_DOWN - 1)
temp &= 0xD;
if(!mptr->cell.x)
temp &= 0xB;
else if(mptr->cell.x == CELLS_ACROSS - 1)
temp &= 0x7;
if(!temp)
temp = valid & 0xF;
if(mptr->pixel.x < monster.list[0].pixel.x)
valid = 0x8;
else if(mptr->pixel.x > monster.list[0].pixel.x)
valid = 0x4;
else
valid = 0;
if(!(valid & temp))
{
if(mptr->pixel.y < monster.list[0].pixel.y)
valid = 0x2;
else if(mptr->pixel.y > monster.list[0].pixel.y)
valid = 0x1;
if(!(valid & temp))
valid = temp;
}
assert(valid);
for(temp = 0; !(valid & 1); temp++)
valid >>= 1;
if(temp != mptr->dir)
{
mptr->dir = temp;
new_face(mptr);
}
move_muncher(mptr);
}
/*}}}*/
}
/*}}}*/
else
/*{{{ pick a direction*/
{
unsigned temp;
if(mptr->cont)
{
valid &= 0xF;
temp = valid & ~(1 << (mptr->dir ^ 1));
if(temp)
valid = temp;
}
else if(valid & 0xF0)
valid = valid & valid >> 4;
valid = choose_direction(valid);
temp = mptr->dir;
if(valid != mptr->dir)
{
mptr->dir = valid;
if(mptr->push && (valid ^ temp) != 1)
{
mptr->push = 0;
mptr->cont = 1;
}
new_face(mptr);
}
if(!apple_stop(mptr, cptr))
cptr = move_movable(mptr, cptr);
if(mptr->push)
{
mptr->dir = temp;
mptr->push = 0;
}
}
/*}}}*/
break;
}
/*}}}*/
/*{{{ case 2: case 3: (xtra or drone)*/
case 2: case 3:
{
int valid;
int temp;
/*{{{ giving birth?*/
if(monster.delay && mptr->type == 2 && global.state == 2)
{
monster.delay--;
if(monster.delay)
break;
if(monster.den)
{
monster.delay = XTRA_BIRTH_DELAY;
monster.den--;
spawn_monster(3, mptr->dir, mptr->face,
mptr->cell.x, mptr->cell.y,
mptr->offset.x, mptr->offset.y);
monster.drones++;
i++;
}
}
/*}}}*/
valid = valid_directions(mptr, cptr);
if(global.state == 3 && !mptr->offset.x && ! mptr->offset.y)
mptr->fast = 1;
/*{{{ pick a direction*/
{
if(valid & 0xF0 &&
(mptr->type != 2 || player.ball.state ||
(global.state == 2 ? mptr->count == monster.farthest :
mptr->count != monster.nearest)))
{
mptr->cont = 0;
valid >>= 4;
}
else
{
temp = valid & ((valid >> 4) ^ 0xF);
if(temp)
valid = temp;
else
valid &= 0xF;
}
valid = choose_direction(valid);
if(valid != mptr->dir)
{
mptr->dir = valid;
new_face(mptr);
}
mptr->count = cptr->distance;
cptr = move_movable(mptr, cptr);
/*{{{ walked into apple?*/
{
unsigned i;
APPLE *aptr;
int x, y;
int width, height;
x = mptr->pixel.x;
y = mptr->pixel.y;
/*{{{ set offset*/
if(mptr->dir & 2)
{
x -= CELL_WIDTH / 2;
y -= CELL_HEIGHT / 4;
width = CELL_WIDTH;
height = CELL_HEIGHT / 2;
}
else
{
x -= CELL_WIDTH / 4;
y -= CELL_HEIGHT / 2;
width = CELL_WIDTH / 2;
height = CELL_HEIGHT;
}
/*}}}*/
for(aptr = apple.list, i = apple.apples; i--; aptr++)
{
if(aptr->state < 3 &&
aptr->pixel.x - x >= 0 &&
aptr->pixel.x - x < width &&
aptr->pixel.y - y >= 0 &&
aptr->pixel.y - y < height)
{
mptr->chew = 1;
aptr->chewed = 1;
break;
}
}
}
/*}}}*/
}
/*}}}*/
break;
}
/*}}}*/
/*{{{ default:*/
default:
assert(0);
break;
/*}}}*/
}
}
}
monster.nearest = nearest;
monster.farthest = farthest;
return;
}
/*}}}*/
/*{{{ void new_xtra()*/
extern void new_xtra FUNCARGVOID
/*
* increments the extra monster, and draws it up
*/
{
draw_extra_letter(extra.select);
if(extra.select == 4)
extra.select = 0;
else
extra.select++;
create_xtra_monster(extra.select);
draw_extra();
return;
}
/*}}}*/
/*{{{ MONSTER *spawn_monster(type, dir, face, cx, cy, ox, oy)*/
extern MONSTER *spawn_monster FUNCARGLIST((type, dir, face, cx, cy, ox, oy))
int type FUNCARGSEP /* type of monster 0-4 */
int dir FUNCARGSEP /* direction 0-3 */
int face FUNCARGSEP /* face 0-5 */
int cx FUNCARGSEP /* cell x */
int cy FUNCARGSEP /* cell y */
int ox FUNCARGSEP /* offset x */
int oy FUNCARGTERM /* offset y */
/*
* creates a new monster onto the monster list
* returns a pointer to the new monster
*/
{
MONSTER *mptr;
assert(monster.monsters != MONSTERS);
assert(!(ox % VEL_X) && !(oy % VEL_Y));
mptr = &monster.list[monster.monsters++];
mptr->dir = dir;
mptr->type = type;
mptr->face = face;
mptr->apple = NULL;
mptr->push = 0;
mptr->gomunch = mptr->cont = mptr->chew = mptr->pause = mptr->stop = 0;
mptr->fast = mptr->pushing = 0;
mptr->count = 0;
mptr->cell.x = cx;
mptr->cell.y = cy;
mptr->offset.x = ox;
mptr->offset.y = oy;
mptr->pixel.x = PIXELX(cx, ox);
mptr->pixel.y = PIXELY(cy, oy);
mptr->image = random() % MONSTER_IMAGES;
mptr->cycle = random() % MONSTER_CYCLES;
mptr->shot = 0;
mptr->old_sprite = 0;
return mptr;
}
/*}}}*/